package com.boot.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.boot.annotation.RateLimit;
import com.boot.entity.ImageInfo;
import com.boot.entity.Question;
import com.boot.entity.Result;
import com.boot.exception.BusinessException;
import com.boot.mapper.ImageInfoMapper;
import com.boot.service.IAttachmentService;
import com.boot.service.IQuestionService;
import com.boot.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import javax.annotation.Resource;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.List;

@RestController
@RequestMapping("/api/attachment")
@Slf4j
public class AttachmentController {

    @Resource
    private IAttachmentService attachmentService;

    @Resource
    private IQuestionService questionService;

    @Resource
    private ImageInfoMapper imageInfoMapper;

    @RateLimit(limit = 50, windowSec = 60)
    @PostMapping("/validate")
    public Result<String> validateFile(@RequestParam("file") MultipartFile file) {
        try {
            SecurityUtils.requireCurrentUserId();
            attachmentService.validateFile(file);
            return Result.success("文件合法");
        } catch (IllegalArgumentException | SecurityException | IllegalStateException | BusinessException e) {
            return Result.fail(e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.fail("系统错误");
        }
    }

    @RateLimit(limit = 10, windowSec = 60)
    @PostMapping("/save/{questionId}")
    public Result<String> saveAttachments(@PathVariable Long questionId, @RequestParam("files") List<MultipartFile> files) {
        try {
            attachmentService.saveAttachmentsForQuestion(files, questionId);
            return Result.success("附件保存成功");
        } catch (IllegalArgumentException | SecurityException | IllegalStateException | BusinessException e) {
            return Result.fail(e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.fail("系统错误");
        }
    }

    @RateLimit(limit = 10, windowSec = 60)
    @PostMapping("/update/{questionId}")
    public Result<String> updateAttachments(@PathVariable Long questionId, @RequestParam("files") List<MultipartFile> files) {
        try {
            attachmentService.updateAttachmentsForQuestion(files, questionId);
            return Result.success("附件保存成功");
        } catch (IllegalArgumentException | SecurityException | IllegalStateException | BusinessException e) {
            return Result.fail(e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.fail("系统错误");
        }
    }

    @RateLimit(limit = 10, windowSec = 60)
    @GetMapping("/download/{questionId}")
    public ResponseEntity<StreamingResponseBody> downloadAttachments(@PathVariable Long questionId) {
        try {
            Long userId = SecurityUtils.requireCurrentUserId();

            Question question = questionService.getById(questionId);
            if (question == null) {
                return ResponseEntity.status(HttpStatus.NOT_FOUND).body(out -> out.write("问题不存在".getBytes(StandardCharsets.UTF_8)));
            }

            if (attachmentService.isNotAssignedOrAcceptedExpert(question, question.getId(), userId)) {
                return ResponseEntity.status(HttpStatus.FORBIDDEN).body(out -> out.write("无权访问".getBytes(StandardCharsets.UTF_8)));
            }

            String filename = "attachments_" + questionId + ".zip";
            String encodedFilename = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", "%20");

            HttpHeaders headers = new HttpHeaders();
            headers.setContentDispositionFormData("attachment", encodedFilename);
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

            StreamingResponseBody streamingBody = outputStream -> attachmentService.streamDownloadAttachmentsAsZip(questionId, outputStream);

            return ResponseEntity.ok()
                    .headers(headers)
                    .body(streamingBody);

        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
        }
    }

    /**
     * 上传图片用于富文本编辑器
     * 返回图片的可访问 URL
     */
    @RateLimit(limit = 10, windowSec = 60)
    @PostMapping(value = "/upload-image", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Result<String> uploadImageForEditor(@RequestParam("file") MultipartFile file) {
        try {
            // 1. 认证校验
            Long userId = SecurityUtils.requireCurrentUserId();

            // 限制每个用户每天最多上传 50 张图片
            // 计算今天的开始和结束时间
            LocalDateTime startOfDay = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
            LocalDateTime endOfDay = startOfDay.plusDays(1);

            QueryWrapper<ImageInfo> wrapper = new QueryWrapper<>();
            wrapper.eq("user_id", userId)
                    .ge("created_at", startOfDay)
                    .lt("created_at", endOfDay);

            Long count = imageInfoMapper.selectCount(wrapper);
            if (count >= 50) {
                throw new BusinessException("今天的上传数量达到限制（最多50张）");
            }

            // 2. 调用服务层处理并获取图片访问 URL
            String imageUrl = attachmentService.uploadImage(file);

            return Result.success(imageUrl);
        } catch (IllegalArgumentException | SecurityException | IllegalStateException | BusinessException e) {
            return Result.fail(e.getMessage());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.fail("系统错误");
        }
    }

    @GetMapping("/image/{imageName}")
    @RateLimit(limit = 60, windowSec = 60)
    public ResponseEntity<StreamingResponseBody> serveImage(@PathVariable String imageName) {
        try {
            return attachmentService.serveImage(imageName);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
        }
    }
}
